<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html lang="en">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<!-- adaptations.qdoc -->
  <title>Qt Quick Direct3D 12 Adaptation | Qt Quick 5.12.3</title>
  <link rel="stylesheet" type="text/css" href="style/offline-simple.css" />
  <script type="text/javascript">
    document.getElementsByTagName("link").item(0).setAttribute("href", "style/offline.css");
    // loading style sheet breaks anchors that were jumped to before
    // so force jumping to anchor again
    setTimeout(function() {
        var anchor = location.hash;
        // need to jump to different anchor first (e.g. none)
        location.hash = "#";
        setTimeout(function() {
            location.hash = anchor;
        }, 0);
    }, 0);
  </script>
</head>
<body>
<div class="header" id="qtdocheader">
  <div class="main">
    <div class="main-rounded">
      <div class="navigationbar">
        <table><tr>
<td ><a href="../qtdoc/index.html">Qt 5.12</a></td><td ><a href="qtquick-index.html">Qt Quick 模块</a></td><td >Qt Quick Direct3D 12 Adaptation</td></tr></table><table class="buildversion"><tr>
<td id="buildversion" width="100%" align="right"><a href="qtquick-index.html">Qt 5.12.3 参考指南</a></td>
        </tr></table>
      </div>
    </div>
<div class="content">
<div class="line">
<div class="content mainContent">
<div class="sidebar">
<div class="toc">
<h3><a name="toc">目录</a></h3>
<ul>
<li class="level2"><a href="#motivation">Motivation</a></li>
<li class="level2"><a href="#graphics-adapters">Graphics Adapters</a></li>
<li class="level2"><a href="#troubleshooting">Troubleshooting</a></li>
<li class="level2"><a href="#render-loops">Render Loops</a></li>
<li class="level2"><a href="#renderer">Renderer</a></li>
<li class="level2"><a href="#shader-effects">Shader Effects</a></li>
<li class="level2"><a href="#multisample-render-targets">Multisample Render Targets</a></li>
<li class="level2"><a href="#semi-transparent-windows">Semi-transparent Windows</a></li>
<li class="level2"><a href="#mipmaps">Mipmaps</a></li>
<li class="level2"><a href="#image-formats">Image Formats</a></li>
<li class="level2"><a href="#unsupported-features">Unsupported Features</a></li>
<li class="level2"><a href="#related-apis">Related APIs</a></li>
<li class="level2"><a href="#advanced-configuration">Advanced Configuration</a></li>
</ul>
</div>
<div class="sidebar-content" id="sidebar-content"></div></div>
<h1 class="title">Qt Quick Direct3D 12 Adaptation</h1>
<span class="subtitle"></span>
<!-- $$$qtquick-visualcanvas-adaptations-d3d12.html-description -->
<div class="descr"> <a name="details"></a>
<p>The Direct3D 12 adaptation for Windows 10 (both Win32 (<code>windows</code> platform plugin) and UWP (<code>winrt</code> platform plugin)) is shipped as a dynamically loaded plugin. It will not be functional on earlier Windows versions. The building of the plugin is enabled automatically whenever the necessary D3D and DXGI develpoment files are present. In practice this currently means Visual Studio 2015 and newer.</p>
<p>The adaptation is available both in normal, OpenGL-enabled Qt builds and also when Qt was configured with <code>-no-opengl</code>. However, it is never the default, meaning the user or the application has to explicitly request it by setting the <code>QT_QUICK_BACKEND</code> environment variable to <code>d3d12</code> or by calling <a href="qquickwindow.html#setSceneGraphBackend">QQuickWindow::setSceneGraphBackend</a>().</p>
<a name="motivation"></a>
<h3 >Motivation</h3>
<p>This experimental adaptation is the first Qt Quick backend focusing on a modern, lower-level graphics API in combination with a windowing system interface different from the traditional approaches used in combination with OpenGL.</p>
<p>It also allows better integration with Windows, Direct3D being the primary vendor-supported solution. This means that there are fewer problems anticipated with drivers, operations like window resizes, and special events like graphics device loss caused by device resets or graphics driver updates.</p>
<p>Performance-wise the general expectation is a somewhat lower CPU usage compared to OpenGL due to lower driver overhead, and a higher GPU utilization with less wasted idle time. The backend does not heavily utilize threads yet, which means there are opportunities for further improvements in the future, for example to further optimize image loading.</p>
<p>The D3D12 backend also introduces support for pre-compiled shaders. All the backend's own shaders (used by the built-in materials on which the Rectangle, Image, Text, etc. QML types are built) are compiled to D3D shader bytecode when compiling Qt. Applications using <a href="qml-qtquick-shadereffect.html">ShaderEffect</a> items can chose to ship bytecode either in regular files or via the Qt resource system, or use HLSL source strings. Unlike OpenGL, the compilation for the latter is properly threaded, meaning shader compilation will not block the application and its user interface.</p>
<a name="graphics-adapters"></a>
<h3 >Graphics Adapters</h3>
<p>The plugin does not necessarily require hardware acceleration. Using WARP, the Direct3D software rasterizer, is also an option. By default the first adapter providing hardware acceleration is chosen. To override this, in order to use another graphics adapter or to force the usage of the software rasterizer, set the environment variable <code>QT_D3D_ADAPTER_INDEX</code> to the index of the adapter. The discovered adapters are printed at startup when <code>QSG_INFO</code> or the logging category <code>qt.scenegraph.general</code> is enabled.</p>
<a name="troubleshooting"></a>
<h3 >Troubleshooting</h3>
<p>When encountering issues, always set the <code>QSG_INFO</code> and <code>QT_D3D_DEBUG</code> environment variables to 1 in order to get debug and warning messages printed on the debug output. The latter enables the Direct3D debug layer. Note that the debug layer should not be enabled in production use since it can significantly impact performance (CPU load) due to increased API overhead.</p>
<a name="render-loops"></a>
<h3 >Render Loops</h3>
<p>By default the D3D12 adaptation uses a single-threaded render loop similar to OpenGL's <code>windows</code> render loop. There is also a threaded variant available, that can be requested by setting the <code>QSG_RENDER_LOOP</code> environment variable to <code>threaded</code>. However, due to conceptual limitations in DXGI, the windowing system interface, the threaded loop is prone to deadlocks when multiple <a href="qquickwindow.html">QQuickWindow</a> or <a href="qquickview.html">QQuickView</a> instances are shown. Therefore the default is the single-threaded loop for the time being. This means that with the D3D12 backend applications are expected to move their work from the main (GUI) thread out to worker threads, instead of expecting Qt to keep the GUI thread responsive and suitable for heavy, blocking operations.</p>
<p>See the <a href="qtquick-visualcanvas-scenegraph.html">Scene Graph page</a> for more information on render loops and <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/ee417025(v=vs.85).aspx#multithreading_and_dxgi">the MSDN page for DXGI</a> regarding the issues with multithreading.</p>
<a name="renderer"></a>
<h3 >Renderer</h3>
<p>The scenegraph renderer in the D3D12 adaptation does not currently perform any batching. This is less of an issue, unlike OpenGL, because state changes are not presenting any problems in the first place. The simpler renderer logic can also lead to lower CPU overhead in some cases. The trade-offs between the various approaches are currently under research.</p>
<a name="shader-effects"></a>
<h3 >Shader Effects</h3>
<p>The <a href="qml-qtquick-shadereffect.html">ShaderEffect</a> QML type is fully functional with the D3D12 adaptation as well. However, the interpretation of the fragmentShader and vertexShader properties is different than with OpenGL.</p>
<p>With D3D12, these strings can either be an URL for a local file or a file in the resource system, or a HLSL source string. The former indicates that the file in question contains pre-compiled D3D shader bytecode generated by the <code>fxc</code> tool, or, alternatively, HLSL source code. The type of the file is detected automatically. This means that the D3D12 backend supports all options from <a href="qml-qtquick-graphicsinfo.html">GraphicsInfo</a>.shaderCompilationType and <a href="qml-qtquick-graphicsinfo.html">GraphicsInfo</a>.shaderSourceType.</p>
<p>Unlike OpenGL, there is a <a href="../qtcore/qfileselector.html">QFileSelector</a> with the extra selector <code>hlsl</code> used whenever opening a file. This allows easy creation of <a href="qml-qtquick-shadereffect.html">ShaderEffect</a> items that are functional across both backends, for example by placing the GLSL source code into <code>shaders/effect.frag</code>, the HLSL source code or - preferably - pre-compiled bytecode into <code>shaders/+hlsl/effect.frag</code>, while simply writing <code>fragmentShader: &quot;qrc:shaders/effect.frag&quot;</code> in QML.</p>
<p>See the <a href="qml-qtquick-shadereffect.html">ShaderEffect</a> documentation for more details.</p>
<a name="multisample-render-targets"></a>
<h3 >Multisample Render Targets</h3>
<p>The Direct3D 12 adaptation ignores the <a href="../qtgui/qsurfaceformat.html">QSurfaceFormat</a> set on the <a href="qquickwindow.html">QQuickWindow</a> or <a href="qquickview.html">QQuickView</a> (or set via <a href="../qtgui/qsurfaceformat.html#setDefaultFormat">QSurfaceFormat::setDefaultFormat</a>()), with two exceptions: <a href="../qtgui/qsurfaceformat.html#samples">QSurfaceFormat::samples</a>() and <a href="../qtgui/qsurfaceformat.html#alphaBufferSize">QSurfaceFormat::alphaBufferSize</a>() are still taken into account. When the samples value is greater than 1, multisample offscreen render targets will be created with the specified sample count and a quality of the maximum supported quality level. The backend automatically performs resolving into the non-multisample swapchain buffers after each frame.</p>
<a name="semi-transparent-windows"></a>
<h3 >Semi-transparent Windows</h3>
<p>When the alpha channel is enabled either via <a href="qquickwindow.html#setDefaultAlphaBuffer">QQuickWindow::setDefaultAlphaBuffer</a>() or by setting alphaBufferSize to a non-zero value in the window's <a href="../qtgui/qsurfaceformat.html">QSurfaceFormat</a> or in the global format managed by <a href="../qtgui/qsurfaceformat.html#setDefaultFormat">QSurfaceFormat::setDefaultFormat</a>(), the D3D12 backend will create a swapchain for composition and go through DirectComposition since the flip model swapchain (which is mandatory) would not support transparency otherwise.</p>
<p>It is therefore important not to unneccessarily request an alpha channel. When the alphaBufferSize is 0 or the default -1, all these extra steps can be avoided and the traditional window-based swapchain is sufficient.</p>
<p>This is not relevant on <a href="../qtdoc/supported-platforms.html#winrt">WinRT</a> because there the backend always uses a composition swapchain which is associated with the ISwapChainPanel that backs <a href="../qtgui/qwindow.html">QWindow</a> on that platform.</p>
<a name="mipmaps"></a>
<h3 >Mipmaps</h3>
<p>Mipmap generation is supported and handled transparently to the applications via a built-in compute shader, but is experimental and only supports power-of-two images at the moment. Textures of other size will work too, but this involves a <a href="../qtgui/qimage.html">QImage</a>-based scaling on the CPU first. Therefore avoid enabling mipmapping for NPOT images whenever possible.</p>
<a name="image-formats"></a>
<h3 >Image Formats</h3>
<p>When creating textures via the C++ scenegraph APIs like <a href="qquickwindow.html#createTextureFromImage">QQuickWindow::createTextureFromImage</a>(), 32-bit formats will not involve any conversion, they will map directly to the corresponding <code>R8G8B8A8_UNORM</code> or <code>B8G8R8A8_UNORM</code> format. Everything else will trigger a <a href="../qtgui/qimage.html">QImage</a>-based format conversion on the CPU first.</p>
<a name="unsupported-features"></a>
<h3 >Unsupported Features</h3>
<p>Particles and some other OpenGL-dependent utilities, like <a href="qquickframebufferobject.html">QQuickFramebufferObject</a>, are not currently supported.</p>
<p>Like with the <a href="qtquick-visualcanvas-adaptations-software.html">Software adaptation</a>, text is always rendered using the native method. Distance field-based text rendering is not currently implemented.</p>
<p>The shader sources in the <a href="../qtgraphicaleffects/qtgraphicaleffects-index.html">Qt Graphical Effects</a> module have not been ported to any format other than the OpenGL 2.0 compatible one, meaning the QML types provided by that module are not currently functional with the D3D12 backend.</p>
<p>Texture atlases are not currently in use.</p>
<p>The renderer may lack support for certain minor features, for example drawing points and lines with a width other than 1.</p>
<p>Custom Qt Quick items using custom scenegraph nodes can be problematic. Materials are inherently tied to the graphics API. Therefore only items using the utility rectangle and image nodes are functional across all adaptations.</p>
<p><a href="qquickwidget.html">QQuickWidget</a> and its underlying OpenGL-based compositing architecture is not supported. If mixing with <a href="../qtwidgets/qwidget.html">QWidget</a>-based user interfaces is desired, use <a href="../qtwidgets/qwidget.html#createWindowContainer">QWidget::createWindowContainer</a>() to embed the native window of the <a href="qquickwindow.html">QQuickWindow</a> or <a href="qquickview.html">QQuickView</a>.</p>
<p>Finally, rendering via <a href="qsgengine.html">QSGEngine</a> and <a href="qsgabstractrenderer.html">QSGAbstractRenderer</a> is not feasible with the D3D12 adaptation at the moment.</p>
<a name="related-apis"></a>
<h3 >Related APIs</h3>
<p>To integrate custom Direct3D 12 rendering, use <a href="qsgrendernode.html">QSGRenderNode</a> in combination with <a href="qsgrendererinterface.html">QSGRendererInterface</a>. This approach does not rely on OpenGL contexts or API specifics like framebuffers, and allows exposing the graphics device and command buffer from the adaptation. It is not necessarily suitable for easy integration of all types of content, in particular true 3D, so it will likely get complemented by an alternative to <a href="qquickframebufferobject.html">QQuickFramebufferObject</a> in future releases.</p>
<p>To perform runtime decisions based on the adaptation in use, use <a href="qsgrendererinterface.html">QSGRendererInterface</a> from C++ and <a href="qml-qtquick-graphicsinfo.html">GraphicsInfo</a> from QML. They can also be used to check the level of shader support (shading language, compilation approach).</p>
<p>When creating custom items, use the new <a href="qsgrectanglenode.html">QSGRectangleNode</a> and <a href="qsgimagenode.html">QSGImageNode</a> classes. These replace the now deprecated QSGSimpleRectNode and QSGSimpleTextureNode. Unlike their predecessors, the new classes are interfaces, and implementations are created via the factory functions <a href="qquickwindow.html#createRectangleNode">QQuickWindow::createRectangleNode</a>() and <a href="qquickwindow.html#createImageNode">QQuickWindow::createImageNode</a>().</p>
<a name="advanced-configuration"></a>
<h3 >Advanced Configuration</h3>
<p>The D3D12 adaptation can keep multiple frames in flight, similarly to modern game engines. This is somewhat different from the traditional render - swap - wait for vsync model and allows better GPU utilization at the expense of higher resource usage. This means that the renderer will be a number of frames ahead of what is displayed on the screen.</p>
<p>For a discussion of flip model swap chains and the typical configuration parameters, refer to <a href="https://software.intel.com/en-us/articles/sample-application-for-direct3d-12-flip-model-swap-chains">this article</a>.</p>
<p>Vertical synchronization is always enabled, meaning Present() is invoked with an interval of 1.</p>
<p>The configuration can be changed by setting the following environment variables:</p>
<ul>
<li><code>QT_D3D_BUFFER_COUNT</code> - The number of swap chain buffers in range 2 - 4. The default value is 3.</li>
<li><code>QT_D3D_FRAME_COUNT</code> - The number of frames prepared without blocking in range 1 - 4. Note that Present will start blocking after queuing 3 frames (regardless of <code>QT_D3D_BUFFER_COUNT</code>), unless the waitable object is in use. Note that every additional frame increases GPU resource usage since geometry and constant buffer data will have to be duplicated, and involves more bookkeeping on the CPU side. The default value is 2.</li>
<li><code>QT_D3D_WAITABLE_SWAP_CHAIN_MAX_LATENCY</code> - When set to a value between 1 and 16, the frame latency is set to the specified value. This changes the limit for Present() and will trigger a wait for an available swap chain buffer when beginning each frame. Refer to the article above for a detailed discussion. This is considered experimental for now and the default value is 0 (disabled).</li>
<li><code>QT_D3D_BLOCKING_PRESENT</code> - When set to a non-zero value, there will be CPU-side wait for the GPU to finish its work after each call to Present. This effectively kills all parallelism but makes the behavior resemble the traditional swap-blocks-for-vsync model, and can therefore be useful in some special cases. This is not the same as setting the frame count to 1 because that still avoids blocking after Present, and may block only when starting to prepare the next frame (or may not block at all depending on the time gap between the frames). By default blocking present is disabled.</li>
</ul>
</div>
<!-- @@@qtquick-visualcanvas-adaptations-d3d12.html -->
        </div>
       </div>
   </div>
   </div>
</div>
<div class="footer">
   <p>
   <acronym title="Copyright">&copy;</acronym> 2019 The Qt Company Ltd.
   Documentation contributions included herein are the copyrights of
   their respective owners.<br/>    The documentation provided herein is licensed under the terms of the    <a href="http://www.gnu.org/licenses/fdl.html">GNU Free Documentation    License version 1.3</a> as published by the Free Software Foundation.<br/>    Qt and respective logos are trademarks of The Qt Company Ltd.     in Finland and/or other countries worldwide. All other trademarks are property
   of their respective owners. </p>
</div>
</body>
</html>
